home *** CD-ROM | disk | FTP | other *** search
Oberon Text | 1992-01-27 | 9.5 KB | 204 lines |
- Syntax10.Scn.Fnt
- MODULE PopupElems; (* Michael Franz, 27.1.92 -- "Hypertext without Surprises" *)
- IMPORT
- Oberon, Input, Display, Viewers, Files, Fonts, Printer, Texts, TextFrames, MenuViewers, WriteFrames, WritePrinter;
- CONST
- edw=4; edh=2; mdw=3; mdh=1; CR=0DX; (* margins of element box and menu box *)
- TYPE
- PopupElem=POINTER TO PopupElemDesc;
- PopupElemDesc=RECORD (Texts.ElemDesc)
- name: ARRAY 32 OF CHAR;
- menu: Texts.Text; n, def, wid, lsp, dsc: INTEGER (* number of items, default, width, line space, descender *)
- END;
- EditFrame=POINTER TO EditFrameDesc;
- EditFrameDesc=RECORD (TextFrames.FrameDesc)
- elem: PopupElem
- END;
- buf: Texts.Buffer; (* copy buffer *)
- (* auxiliary *)
- PROCEDURE Min(x, y: INTEGER): INTEGER;
- BEGIN IF x<y THEN RETURN x ELSE RETURN y END
- END Min;
- PROCEDURE Max(x, y: INTEGER): INTEGER;
- BEGIN IF x>y THEN RETURN x ELSE RETURN y END
- END Max;
- (* change propagation *)
- PROCEDURE SetupElem(E: PopupElem; fnt: Fonts.Font);
- VAR i, wid, dx, x, y, w, h: INTEGER; p: LONGINT;
- BEGIN i:=0; wid:=2*edw+4;
- LOOP
- IF E.name[i]=0X THEN E.W:=(wid+1)*Display.Unit; E.H:=(fnt.height-fnt.minY+2*edh+2)*Display.Unit; RETURN
- ELSE Display.GetChar(fnt.raster, E.name[i], dx, x, y, w, h, p); INC(wid, dx); INC(i) END
- END
- END SetupElem;
- PROCEDURE SetupMenu(E: PopupElem);
- VAR R: Texts.Reader; ch: CHAR; wid, dx, x, y, w, h: INTEGER; p: LONGINT;
- BEGIN Texts.OpenReader(R, E.menu, 0); E.wid:=0; E.n:=1; E.lsp:=0; wid:=0;
- LOOP Texts.Read(R, ch);
- IF R.eot THEN E.wid:=Max(E.wid, wid); E.def:=Min(E.def, E.n); RETURN
- ELSIF ch=CR THEN E.wid:=Max(E.wid, wid); wid:=0; INC(E.n)
- ELSE E.lsp:=Max(E.lsp, R.fnt.height); E.dsc:=Min(E.dsc, R.fnt.minY);
- Display.GetChar(R.fnt.raster, ch, dx, x, y, w, h, p); INC(wid, dx)
- END
- END
- END SetupMenu;
- (* interactive editing of popup menus *)
- PROCEDURE* EditHandle(F: Display.Frame; VAR M: Display.FrameMsg);
- VAR F1: EditFrame;
- BEGIN
- WITH F:EditFrame DO TextFrames.Handle(F, M);
- IF ((M IS Oberon.InputMsg) & (M(Oberon.InputMsg).id=Oberon.consume)) OR (M IS TextFrames.UpdateMsg) THEN
- SetupMenu(F.elem)
- ELSIF M IS Oberon.CopyMsg THEN NEW(F1);
- TextFrames.Open(F1, F.handle, F.text, F.org, F.col, F.left, F.right, F.top, F.bot, F.lsp); F1.elem:=F.elem; M(Oberon.CopyMsg).F:=F1
- END
- END
- END EditHandle;
- PROCEDURE OpenEditor(E: PopupElem);
- VAR V: Viewers.Viewer; F: EditFrame; x, y: INTEGER;
- BEGIN Oberon.AllocateUserViewer(Oberon.Par.vwr.X, x, y); NEW(F); F.elem:=E;
- TextFrames.Open(F, EditHandle, E.menu, 0, Display.black, TextFrames.left, TextFrames.right, TextFrames.top, TextFrames.bot, 0);
- V:=MenuViewers.New(TextFrames.NewMenu(E.name, "System.Close System.Grow"), F, TextFrames.menuH, x, y)
- END OpenEditor;
- (* file input/output *)
- PROCEDURE Load(VAR R: Files.Rider; E: PopupElem);
- VAR F: Files.File; ch: CHAR; i: INTEGER; pos, len: LONGINT;
- BEGIN i:=0; REPEAT Files.Read(R, ch); E.name[i]:=ch; INC(i) UNTIL ch=0X;
- E.name[i-1]:="."; E.name[i]:="."; E.name[i+1]:="."; E.name[i+2]:=0X; SetupElem(E, Fonts.Default);
- Files.Read(R, ch); E.def:=ORD(ch); E.menu:=TextFrames.Text("");
- pos:=Files.Pos(R)+2; F:=Files.Base(R); Texts.Load(E.menu, F, pos, len); Files.Set(R, F, pos+len)
- END Load;
- PROCEDURE Store(VAR R: Files.Rider; E: PopupElem);
- VAR F: Files.File; i: INTEGER; pos, len: LONGINT;
- BEGIN i:=0; WHILE E.name[i] # 0X DO INC(i) END;
- Files.WriteBytes(R, E.name, i-3); Files.Write(R, 0X); Files.Write(R, CHR(E.def MOD 128));
- pos:=Files.Pos(R); F:=Files.Base(R); len:=E.menu.len; Texts.Store(E.menu, F, pos, len); Files.Set(R, F, pos+len)
- END Store;
- (* graphics *)
- PROCEDURE Box(col, X, Y, W, H: INTEGER);
- BEGIN
- Display.ReplConst(col, X+1, Y+1, W-2, 1, Display.replace);
- Display.ReplConst(col, X+1, Y+H-2, W-2, 1, Display.replace);
- Display.ReplConst(col, X+1, Y+2, 1, H-4, Display.replace);
- Display.ReplConst(col, X+W-2, Y+2, 1, H-4, Display.replace);
- Display.ReplConst(col, X+4, Y, W-4, 1, Display.replace);
- Display.ReplConst(col, X+W-1, Y+1, 1, H-4, Display.replace);
- Display.ReplConst(Display.black, X+2, Y+2, W-4, H-4, Display.replace)
- END Box;
- PROCEDURE PrintElem(E: PopupElem; X, Y: INTEGER; fnt: Fonts.Font);
- VAR W, H: INTEGER;
- BEGIN W:=SHORT((E.W-1) DIV WritePrinter.Unit); H:=SHORT(E.H DIV WritePrinter.Unit);
- Printer.ReplConst(X, Y, W, 2);
- Printer.ReplConst(X, Y+H-2, W, 2);
- Printer.ReplConst(X, Y+2, 2, H-4);
- Printer.ReplConst(X+W-2, Y+2, 2, H-4);
- Printer.String(X+edw+2, Y+edh+2+fnt.minY, E.name, fnt.name)
- END PrintElem;
- PROCEDURE DrawElem(E: PopupElem; col, X, Y: INTEGER; fnt: Fonts.Font);
- VAR i, dx, x, y, w, h: INTEGER; p: LONGINT;
- BEGIN Box(col, X, Y, SHORT((E.W-1) DIV WriteFrames.Unit), SHORT(E.H DIV WriteFrames.Unit));
- INC(X, edw+2); INC(Y, edh+2-fnt.minY); i:=0;
- WHILE E.name[i] >= " " DO Display.GetChar(fnt.raster, E.name[i], dx, x, y, w, h, p);
- Display.CopyPattern(col, p, X+x, Y+y, Display.replace); INC(X, dx); INC(i)
- END
- END DrawElem;
- PROCEDURE DrawMenu(E: PopupElem; X, Y, W, H: INTEGER);
- VAR R: Texts.Reader; ch: CHAR; X0, dx, x, y, w, h: INTEGER; p: LONGINT;
- BEGIN Box(Display.white, X, Y, W, H); Texts.OpenReader(R, E.menu, 0); X0:=X+mdw+2; X:=X0; Y:=Y+H-E.lsp-E.dsc-mdh-2;
- LOOP Texts.Read(R, ch);
- IF R.eot THEN RETURN
- ELSIF ch=CR THEN Y:=Y-E.lsp; X:=X0
- ELSE Display.GetChar (R.fnt.raster, ch, dx, x, y, w, h, p);
- Display.CopyPattern(Display.white, p, X+x, Y+y, Display.replace); INC(X, dx)
- END
- END
- END DrawMenu;
- (* actions *)
- PROCEDURE Show(E: PopupElem; X, Y, W, H: INTEGER; VAR cmd: INTEGER);
- VAR mx, my, top, bot, left, right, newCmd: INTEGER; keys: SET;
- BEGIN left:=X+3; right:=X+W-3; bot:=Y+mdh+3; top:=Y+H-mdh-2;
- Oberon.RemoveMarks(X, Y, W, H); Oberon.FadeCursor(Oberon.Mouse);
- Display.CopyBlock(X, Y, W, H, X, -H, Display.replace); DrawMenu(E, X, Y, W, H);
- Display.ReplConst(Display.white, X+3, top-cmd*E.lsp-E.lsp, W-6, E.lsp, Display.invert);
- REPEAT Input.Mouse(keys, mx, my); Oberon.DrawCursor(Oberon.Mouse, Oberon.Arrow, mx, my);
- IF keys*{0,2} # {} THEN Oberon.FadeCursor(Oberon.Mouse); Display.CopyBlock(X, -H, W, H, X, Y, Display.replace);
- IF 0 IN keys THEN OpenEditor(E) END;
- REPEAT Input.Mouse(keys, mx, my); Oberon.DrawCursor(Oberon.Mouse, Oberon.Arrow, mx, my) UNTIL keys={};
- cmd:=-1; RETURN
- ELSIF (mx>=left) & (mx<=right) & (my>=bot) & (my<=top) THEN newCmd:=(top-my) DIV E.lsp;
- IF newCmd # cmd THEN
- IF cmd # -1 THEN Display.ReplConst(Display.white, X+3, top-cmd*E.lsp-E.lsp, W-6, E.lsp, Display.invert) END;
- Display.ReplConst(Display.white, X+3, top-newCmd*E.lsp-E.lsp, W-6, E.lsp, Display.invert); cmd:=newCmd
- END
- ELSIF cmd # -1 THEN
- Display.ReplConst(Display.white, X+3, top-cmd*E.lsp-E.lsp, W-6, E.lsp, Display.invert); cmd:=-1
- END
- UNTIL keys={};
- Oberon.FadeCursor(Oberon.Mouse); Display.CopyBlock(X, -H, W, H, X, Y, Display.replace);
- END Show;
- PROCEDURE Popup(E: PopupElem; X, Y: INTEGER; F: Display.Frame);
- VAR W, H, mx, my, i, j, cmd, res: INTEGER; cmdStr: ARRAY 32 OF CHAR; r: Texts.Reader; ch: CHAR; keys: SET;
- BEGIN Input.Mouse(keys, mx, my); W:=E.wid+2*mdw+4; H:=E.n*E.lsp+2*mdh+4;
- Y:=Max(my-H+E.lsp+E.def*E.lsp, 0); cmd:=E.def;
- IF X+W > Display.Width THEN X:=Display.Width-W END;
- IF Y+H > Display.Height THEN Y:=Display.Height-H END;
- Show(E, X, Y, W, H, cmd);
- IF cmd > -1 THEN E.def:=cmd; j:=0; Texts.OpenReader(r, E.menu, 0); Texts.Read(r, ch);
- WHILE j < cmd DO
- IF ch=CR THEN INC(j) END;
- Texts.Read(r, ch)
- END;
- i:=0; WHILE (ch>" ") & (ch#CR) & (i<31) DO cmdStr[i]:=ch; INC(i); Texts.Read(r, ch) END; cmdStr[i]:=0X;
- Oberon.Par.frame:=F; Oberon.Par.text:=E.menu; Oberon.Par.pos:=Texts.Pos(r); Oberon.Call(cmdStr, Oberon.Par, FALSE, res)
- END
- END Popup;
- (* element *)
- PROCEDURE* Handle(E: Texts.Elem; VAR msg: Texts.ElemMsg);
- VAR e: PopupElem;
- BEGIN
- WITH E:PopupElem DO
- IF msg IS WriteFrames.DisplayMsg THEN
- WITH msg:WriteFrames.DisplayMsg DO
- IF msg.prepare THEN SetupElem(E, msg.fnt)
- ELSE DrawElem(E, msg.col, msg.X0, msg.Y0, msg.fnt) END
- END
- ELSIF msg IS WritePrinter.PrintMsg THEN
- WITH msg:WritePrinter.PrintMsg DO
- IF ~msg.prepare THEN PrintElem(E, msg.X0, msg.Y0, msg.fnt) END
- END
- ELSIF msg IS Texts.CopyMsg THEN
- WITH msg:Texts.CopyMsg DO
- NEW(e); Texts.CopyElem(E, e); e.name:=E.name; e.def:=E.def; e.wid:=E.wid; e.lsp:=E.lsp; e.dsc:=E.dsc; e.n:=E.n;
- e.menu:=TextFrames.Text(""); Texts.Save(E.menu, 0, E.menu.len, buf); Texts.Append(e.menu, buf); msg.e:=e
- END
- ELSIF msg IS Texts.IdentifyMsg THEN
- WITH msg:Texts.IdentifyMsg DO
- msg.mod:="PopupElems"; msg.proc:="Alloc"
- END
- ELSIF msg IS Texts.FileMsg THEN
- WITH msg:Texts.FileMsg DO
- IF msg.id=Texts.load THEN Load(msg.r, E); SetupMenu(E)
- ELSIF msg.id=Texts.store THEN Store(msg.r, E) END
- END
- ELSIF msg IS WriteFrames.TrackMsg THEN
- WITH msg:WriteFrames.TrackMsg DO
- IF msg.keys={1} THEN Popup(E, msg.X0, msg.Y0, msg.frame) END
- END
- END
- END
- END Handle;
- PROCEDURE Alloc*;
- VAR E: PopupElem;
- BEGIN NEW(E); E.handle:=Handle; Texts.new:=E
- END Alloc;
- PROCEDURE Insert*;
- VAR E: PopupElem; S: Texts.Scanner; i: INTEGER;
- BEGIN NEW(E); Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S);
- IF S.class # Texts.String THEN S.s:="Popup" END;
- i:=0; REPEAT E.name[i]:=S.s[i]; INC(i) UNTIL S.s[i]=0X;
- E.name[i]:="."; E.name[i+1]:="."; E.name[i+2]:="."; E.name[i+3]:=0X; SetupElem(E, Fonts.Default);
- E.menu:=TextFrames.Text(""); SetupMenu(E); E.handle:=Handle; WriteFrames.CopyToFocus(E)
- END Insert;
- BEGIN NEW(buf); Texts.OpenBuf(buf)
- END PopupElems.
-